﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace dst
{
    class Program
    {
        static int THREAD_C = 1;
        static void Main(string[] args)
        {
            Thread[] threads = new Thread[THREAD_C];
            for (int i = 0; i < THREAD_C; i++)
            {
                threads[i] = new Thread(new ParameterizedThreadStart(Tmvp));
                threads[i].Start(i);
            }
        }

        static void Cal571()
        {
            Polynomial irp = Polynomial.GenNumePol(571, 10, 5, 2, 0);
            //Console.WriteLine(irp.ToString("B,<"));


            Polynomial a = Polynomial.Parse("0100010010011110000110000101111110000001111110100011110010110110101101100100100100110001110011001110001110011000000111011111010111010110100101110100001011011000111010100111101111010000100100100111100000010100100111100010110101110000010001011101000111101101010101100101111000010101001001101110110111000101101101011011101110011100000101001100010010100001010011100001110011100000001011001001011001010100101000110110011110011111010001001111001100000000110011110010010100100100111101110100000010110111110010110101011101111000001010100101100101110111000010101100001111010111101");
            Polynomial b = Polynomial.Parse("1010100001000000011100100001111100010001100010011000010110100100110111001011010100111111101000101011110011100011001001101001000101010010011100101001100100001000111011111100111100010111011000110001001011010011001101111100111101100110011010100011011111010110111111011101111011010011100111010010000101011001001011110101001110110000001101111010111000111011000000001000011101001001000110000101001011110100101010110101010011010110100010111011001100100001011000111001110100011011111101001100111000100100011010011110011100010011111101111010001000111101010100010010010101101010011");

            Polynomial c = a * b;
            Polynomial e = c.Mod(irp, 570, 0);
            Console.WriteLine(e.ToString("B>", 570, 0));
        }

        static void Tmvp(object tno)
        {
            DateTime dt1, dt2;
            dt1 = DateTime.Now;

            int[][] irps = IRPS.p_espx4;         //need change

            int SHIFT = -0;

            System.IO.StreamWriter fw = new System.IO.StreamWriter("D:/p" + irps[0][0] + "_" + tno + "_" + DateTime.Now.Ticks + ".txt");
            //Polynomial a = Polynomial.GenSymbPol("a", DEGREE);
            //Polynomial b = Polynomial.GenSymbPol("b", DEGREE);
            //Polynomial c = a * b;
            fw.WriteLine("excel_filter, Max_add, Total_XOR, #XOR_after_simp, Total_6In_LUT, Shift, irp");

            int len = irps.Length;
            for (int ip = (int)tno * len / THREAD_C; (ip < ((int)tno + 1) * len / THREAD_C) && ip < irps.Length; ip++)
            {
                Console.WriteLine("irp: " + ip);
                Polynomial irp = Polynomial.GenNumePol(irps[ip]);
                //Polynomial e = c.Clone();
                int DEGREE = irps[ip][0]; 

                fw.WriteLine("Irreducible Polynomial = " + string.Join(",", irps[ip]));
                fw.Flush();

                Console.WriteLine("shift : ");
                Matrix<Exp> m = null;


                for (int iShift = 0; iShift > -DEGREE; iShift--)
                {
                    Console.Write(iShift);
                    SHIFT = iShift;
                    fw.WriteLine("Shift: " + SHIFT + ", irp:" + string.Join(",", irps[ip]));
                    fw.Flush();

                    //e = e.Mod(irp, DEGREE + SHIFT - 1, 0 + SHIFT);
                    //Matrix<Exp> m = e.FactorToToeplitz(irp, eles);

                    m = Polynomial.FactorToToeplitz(m, irp, -iShift);

                    int maxAdd = 0;
                    int totXOR = 0;
                    int totLUT = 0;

                    List<Exp> outlist = new List<Exp>();

                    for (int i = m.Order - 1; i >= 0; i--)
                    {
                        if (m[i, 0] is AddExp<Exp>)
                        {
                            totXOR += ((AddExp<Exp>)m[i, 0]).Count - 1;
                            totLUT++;
                            if (((AddExp<Exp>)m[i, 0]).Count > maxAdd)
                                maxAdd = ((AddExp<Exp>)m[i, 0]).Count;
                        }
                        m[i, 0].SortSubs();
                        outlist.Add(m[i, 0]);
                        fw.Write(m[i, 0] + ",");
                    }
                    for (int i = 1; i < m.Order; i++)
                    {
                        if (m[0, i] is AddExp<Exp>)
                        {
                            totXOR += ((AddExp<Exp>)m[0, i]).Count - 1;
                            totLUT++;
                            if (((AddExp<Exp>)m[0, i]).Count > maxAdd)
                                maxAdd = ((AddExp<Exp>)m[0, i]).Count;
                        }
                        m[0, i].SortSubs();
                        outlist.Add(m[0, i]);
                        fw.Write(m[0, i] + ",");
                    }


                    //想找到最小的面积
                    SimplifySet simpset = new SimplifySet();
                    simpset.Add(outlist);
                    simpset.Simplify();

                    fw.WriteLine();
                    fw.WriteLine(simpset.Output());

                    fw.WriteLine();
                    fw.WriteLine("excel_filter, " + maxAdd + ", " + totXOR + ", " + simpset.TotalXOR + ", " + totLUT + ", " + SHIFT + ", \"" + string.Join(",", irps[ip]) + "\"");
                    //fw.WriteLine("is toeplitz: " + m.isToeplitz());
                    fw.WriteLine();
                    fw.WriteLine();
                    fw.Flush();

                    //e = e >> 2;
                    for(int i = 0; i < iShift.ToString().Length; i++)
                        Console.Write((char)0x8);
                } //end for(iShift
                
            } //end for(ip
            dt2 = DateTime.Now;
            Console.WriteLine("Running Time: " + (dt2 - dt1));
        } //Main

            }
}
